package net.sk.china.front.service.impl.product;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.sk.china.common.exception.TalkException;
import net.sk.china.common.model.product.StoreProduct;
import net.sk.china.common.model.product.StoreProductAttr;
import net.sk.china.common.model.product.StoreProductAttrValue;
import net.sk.china.common.model.product.StoreProductDescription;
import net.sk.china.front.constants.Constants;
import net.sk.china.front.dao.product.StoreProductDao;
import net.sk.china.front.response.product.ProductDetailResponse;
import net.sk.china.front.response.product.StoreProductAttrValueResponse;
import net.sk.china.front.service.product.*;
import net.sk.china.front.service.user.UserService;
import net.sk.china.front.token.TokenComponent;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;

/**
 * StoreProductServiceImpl 接口实现
 * +----------------------------------------------------------------------
 * | Talk To [ 聊来改善地区金融服务环境，助力企业发展 ]
 * +----------------------------------------------------------------------
 * | Copyright (c) 2018-2024 聊来All rights reserved.
 * +----------------------------------------------------------------------
 * | Licensed ( <a href="http://www.apache.org/licenses/LICENSE-2.0">apache</a> )
 * +----------------------------------------------------------------------
 * | @Author: 聊来 <18970881148@qq.com>
 * +----------------------------------------------------------------------
 * | DateTime: 2024/6/12 16:07
 * +----------------------------------------------------------------------
 */

@Service
public class StoreProductServiceImpl extends ServiceImpl<StoreProductDao, StoreProduct> implements StoreProductService {

    @Resource
    private StoreProductDao dao;

    private final StoreProductDescriptionService storeProductDescriptionService;

    private final StoreProductAttrService storeProductAttrService;

    private final StoreProductAttrValueService storeProductAttrValueService;

    private final StoreProductRelationService storeProductRelationService;

    private final ApplicationContext applicationContext;

    private final TokenComponent tokenComponent;

    public StoreProductServiceImpl(StoreProductDescriptionService storeProductDescriptionService, StoreProductAttrService storeProductAttrService,
                                   StoreProductAttrValueService storeProductAttrValueService, StoreProductRelationService storeProductRelationService,
                                   ApplicationContext applicationContext, TokenComponent tokenComponent) {
        this.storeProductDescriptionService = storeProductDescriptionService;
        this.storeProductAttrService = storeProductAttrService;
        this.storeProductAttrValueService = storeProductAttrValueService;
        this.storeProductRelationService = storeProductRelationService;
        this.applicationContext = applicationContext;
        this.tokenComponent = tokenComponent;
    }

    /**
     * 获取商品详情
     * @param id 商品编号
     * @param type normal-正常，void-视频
     * @return {@code ProductDetailResponse}
     */
    @Override
    public ProductDetailResponse getDetail(Integer id, String type) {
        ProductDetailResponse productDetailResponse = new ProductDetailResponse();

        // 详情
        StoreProduct storeProduct = getH5Detail(id);
        productDetailResponse.setProductInfo(storeProduct);

        // 获取商品规格
        List<StoreProductAttr> attrList = storeProductAttrService.getListByProductIdAndType(storeProduct.getId(), Constants.NUM_ZERO);
        // 根据制式设置attr属性
        productDetailResponse.setProductAttr(attrList);

        // 根据制式设置sku属性
        HashMap<String, Object> skuMap = CollUtil.newHashMap();
        List<StoreProductAttrValue> storeProductAttrValues = storeProductAttrValueService.getListByProductIdAndType(storeProduct.getId(), Constants.NUM_ZERO);
        for (StoreProductAttrValue storeProductAttrValue : storeProductAttrValues) {
            StoreProductAttrValueResponse atr = new StoreProductAttrValueResponse();
            BeanUtils.copyProperties(storeProductAttrValue, atr);
            skuMap.put(atr.getSuk(), atr);
        }
        productDetailResponse.setProductValue(skuMap);

        Integer uid = tokenComponent.getUserId();
        if (ObjectUtil.isNull(uid)) {
            productDetailResponse.setUserCollect(false);
        } else {
            productDetailResponse.setUserCollect(storeProductRelationService.getLikeOrCollectByUser(uid, id,false).size() > 0);
        }

        // 解决同一类中异步注解@Async失效问题 商品浏览数+1
        StoreProductServiceImpl bean = applicationContext.getBean(StoreProductServiceImpl.class);
        bean.incBrowse(id);

        return productDetailResponse;
    }

    /**
     * 获取购物车商品信息
     * @param productId 商品编号
     * @return {@code StoreProduct}
     */
    @Override
    public StoreProduct getCartByProId(Integer productId) {
        LambdaQueryWrapper<StoreProduct> query = new LambdaQueryWrapper<>();
        query.select(StoreProduct::getId, StoreProduct::getImage, StoreProduct::getStoreName);
        query.eq(StoreProduct::getId, productId);

        return dao.selectOne(query);
    }

    /**
     * 添加/扣减库存
     * @param id 商品id
     * @param num 数量
     * @param type 类型：add—添加，sub—扣减
     * @return {@code boolean}
     */
    @Override
    public boolean operationStock(Integer id, Integer num, String type) {
        UpdateWrapper<StoreProduct> updateWrapper = new UpdateWrapper<>();
        if (type.equals("add")) {
            updateWrapper.setSql(StrUtil.format("stock = stock + {}", num));
            updateWrapper.setSql(StrUtil.format("sales = sales - {}", num));
        }
        if (type.equals("sub")) {
            updateWrapper.setSql(StrUtil.format("stock = stock - {}", num));
            updateWrapper.setSql(StrUtil.format("sales = sales + {}", num));
            // 扣减时加乐观锁保证库存不为负
            updateWrapper.last(StrUtil.format(" and (stock - {} >= 0)", num));
        }
        updateWrapper.eq("id", id);
        boolean update = update(updateWrapper);
        if (!update) {
            throw new TalkException("更新普通商品库存失败,商品id = " + id);
        }
        return true;
    }

    /**
     * 商品详情
     * @param id 数据ID
     * @return {@code StoreProduct}
     */
    private StoreProduct getH5Detail(Integer id) {
        LambdaQueryWrapper<StoreProduct> query = new LambdaQueryWrapper<>();
        query.select(StoreProduct::getId, StoreProduct::getImage, StoreProduct::getStoreName, StoreProduct::getSliderImage,
                StoreProduct::getOtPrice, StoreProduct::getStock, StoreProduct::getSales, StoreProduct::getPrice, StoreProduct::getActivity,
                StoreProduct::getFicti, StoreProduct::getIsSub, StoreProduct::getStoreInfo, StoreProduct::getBrowse, StoreProduct::getUnitName);
        query.eq(StoreProduct::getId, id);
        query.eq(StoreProduct::getIsRecycle, false);
        query.eq(StoreProduct::getIsDel, false);
        query.eq(StoreProduct::getIsShow, true);
        StoreProduct storeProduct = dao.selectOne(query);
        if (ObjectUtil.isNull(storeProduct)) {
            throw new TalkException(StrUtil.format("未找到编号为{}的商品", id));
        }

        StoreProductDescription description = storeProductDescriptionService.getOne(
                new LambdaQueryWrapper<StoreProductDescription>()
                        .eq(StoreProductDescription::getProductId, storeProduct.getId())
                        .eq(StoreProductDescription::getType, Constants.NUM_ZERO));
        if (ObjectUtil.isNotNull(description)) {
            storeProduct.setContent(StrUtil.isBlank(description.getDescription()) ? "" : description.getDescription());
        }
        return storeProduct;
    }

    /**
     * 商品浏览数+1
     * @param id 数据ID
     */
    @Async("taskExecutor")
    public void incBrowse(Integer id) {
        UpdateWrapper<StoreProduct> query = new UpdateWrapper<>();
        query.setSql("browse = browse + 1");
        query.eq("id", id);

        dao.update(null, query);
    }
}
